/*
 
 /*
  Daniel Brümmel
  Markus Saradjuk
  
  Computer Vision 
  Header Ball Game
 */


#include <stdio.h>
#include <opencv/OpenCV.h>
#include <opencv/highgui.h>
#include <time.h>

#include "Ball.h"

CvCapture *capture = 0;
int show = 0;
CvScalar pixel;
int h,s,v;

int ball_y = 0;
Ball *allBalls[10];
float percent = 60;

// Create memory for calculations
static CvMemStorage* storage = 0;

// Create a new Haar classifier
static CvHaarClassifierCascade* cascade = 0;

// Function prototype for detecting and drawing an object from an image
void detect_and_draw( IplImage* image );

// Create a string that contains the cascade name
const char* cascade_name =
"haarcascade_frontalface_alt.xml";
//"haarcascade_profileface.xml";
//"haarcascade_mcs_upperbody.xml";
//"haarcascade_eye.xml";


void OverlayImage(IplImage* src, IplImage* overlay, CvPoint location);
void windowEchos(IplImage *img);
void startGame();
void endGame();

IplImage *frame, *frame_copy, *gray_image = 0;

IplImage *img2 = 0;

int fps = 0;
int fps_store = 0;
int showCounter = 0;

int showFPS = 0;

time_t time_store;
time_t gameTimeStart;
int gamePoints = 0;
int gameState = 0;

CvSeq* faces;

CvFont font;

int main (int argc, const char * argv[]) {
	
	int NumUploadedFunction = 0;
	NumUploadedFunction = cvUseOptimized(1);
	printf("\t NumUploadedFunction = %d \n\n", NumUploadedFunction);
	
	const char* opencv_lib = 0;
	const char* add_modules = 0;
	cvGetModuleInfo(0, &opencv_lib,&add_modules);
	printf("\t opencv_lib = %s,\n\t add_modules = %s\n\n", opencv_lib,add_modules);
	
	
	
	/* initialize camera */
    capture = cvCaptureFromCAM( 0 );
	frame = cvQueryFrame( capture );
	
	for (int i = 0; i < 10; i++) {
		allBalls[i] = new Ball(frame->width);
	}
	
    int key = 0;
	img2 = cvLoadImage("fussball.jpg", 0);
	// Load the HaarCascade classifier for face detection.
	// Haar Cascade file, used for Face Detection.
	
	// load and set font
	// properties
	double hScale=1.0;
	double vScale=1.0;
	int    lineWidth=2;
	cvInitFont(&font,CV_FONT_HERSHEY_SIMPLEX|CV_FONT_ITALIC, hScale,vScale,0,lineWidth, 0);
	
	// Load the HaarClassifierCascade
    cascade = (CvHaarClassifierCascade*)cvLoad( cascade_name, 0, 0, 0 );
	
	// Allocate the memory storage
    storage = cvCreateMemStorage(0);
	
    /* always check */
    if ( !capture ) {
        fprintf( stderr, "Cannot open initialize webcam!\n" );
        return 1;
    }
	
	
    while( key != 'q' ) {
		
		time_t seconds;
		seconds = time (NULL);
		
		if(seconds - time_store >= 1){
			time_store = seconds;
			fps_store = fps;
			fps = 0;
		}
		fps++;
		
		frame = cvQueryFrame( capture );
		detect_and_draw( frame );
		windowEchos( frame );
		
		if(showFPS == 1){
			char buffer [50];
			sprintf(buffer, "fps %i", fps_store);
			cvPutText (frame,buffer,cvPoint(10,frame->height-10), &font, cvScalar(0,0,255, 0));
		}
		
		
		time_t tmpTime = time (NULL);
		int diff =  (int) (tmpTime - gameTimeStart);
		
		if( gameState == 1 && diff > 10){
			endGame();
		}
		
		cvShowImage( "result", frame);
		
        key = cvWaitKey( 1 );
		if(key == 'f') showFPS = (showFPS==0) ? 1 : 0;
		if(key == 'n'){ startGame(); }
		if(key == 'e'){ endGame(); }
    }
	
    /* free memory */
    cvDestroyWindow( "result" );
	cvReleaseImage( &frame_copy );
    cvReleaseCapture( &capture );
	
    return 0;
}
// ****

// Function to detect and draw any faces that is present in an image
void detect_and_draw( IplImage* img )
{
	// flips image
	// to elimiate the mirror effect!
	// left =! left movement!!
	cvFlip(img, NULL, 1);
	
    // Create two points to represent the face locations
    CvPoint pt1, pt2;
    int i;
	
    // Find whether the cascade is loaded, to find the faces. If yes, then:
    if( cascade && showCounter%5 == 0 )
    {
		IplImage *temp = cvCreateImage
		( cvSize((int)((img->width*percent)/100) , (int)((img->height*percent)/100) ),
		 img->depth, img->nChannels );
		
		//use cvResize to resize source to a destination image
		cvResize(img, temp, CV_INTER_LINEAR);
		
		// Clear the memory storage which was used before
		cvClearMemStorage( storage );
		
		showCounter = 1;
        // Detect the objects and store them in the sequence
		faces = cvHaarDetectObjects(temp, cascade, storage,
									1.3, 2, CV_HAAR_DO_CANNY_PRUNING, //CV_HAAR_SCALE_IMAGE,  //,CV_HAAR_FIND_BIGGEST_OBJECT, , //CV_HAAR_DO_CANNY_PRUNING
									cvSize(60, 60) );
		
		// Release the temp image created.
		cvReleaseImage( &temp );
    }
	
	//no face detect
	// show an information
	if((faces ? faces->total : 0) == 0){
		cvPutText (img,"No face detect!",cvPoint(img->width-300,img->height-10), &font, cvScalar(0,0,255, 0));
	} else {
		// Loop the number of faces found.
		for( i = 0; i < (faces ? faces->total : 0); i++ )
		{
			// Create a new rectangle for drawing the face
			CvRect* r = (CvRect*)cvGetSeqElem( faces, i );
			
			// Find the dimensions of the face,and scale it if necessary
			pt1.x = r->x*100/percent;
			pt2.x = (r->x+r->width)*100/percent;
			pt1.y = r->y*100/percent;
			pt2.y = (r->y+r->height)*100/percent;
			
			cvRectangle( img, pt1, pt2, CV_RGB(255,0,0), 3, 8, 0 );
			
			
			for (int i = 0; i < 10; i++) {
				if (allBalls[i]->chkCollission(pt1, pt2) == true)
				{
					allBalls[i] = new Ball(img->height);
					allBalls[i]->setMovement(i+1);
					if( gameState == 1){
						int substract = pt2.x-pt1.x;
						gamePoints += img->width-substract;
					}
				}
				
			}
		}
	}
	
	showCounter++;
	
	// show balls
	for (int i = 0; i < 10; i++) {
		if(allBalls[i]->getY() > img->height){ allBalls[i] = new Ball(img->width); }
		allBalls[i]->move();
		allBalls[i]->draw(frame);
	}
	
}

/*
  show informations
 */
void windowEchos(IplImage *img){
	// Game is running
	if (gameState == 1) {
		// echo points
		char buffer_points [50];
		sprintf(buffer_points, "Points: %i", gamePoints);
		cvPutText (img,buffer_points,cvPoint(5,30), &font, cvScalar(255,0,0, 0));
		
		time_t tmpTime = time (NULL);
		
		// echo timer
		char buffer_countdown [50];
		sprintf(buffer_countdown, "Time: %li", tmpTime-gameTimeStart);
		cvPutText (img,buffer_countdown,cvPoint(img->width-200,30), &font, cvScalar(255,0,0, 0));
	}else if (gameState == 2) {
		// Game is finished
		// echo timer
		
		cvRectangle(img, cvPoint(0, img->height/2-80 ), cvPoint(img->width, img->height/2+40), cvScalar(255,255,255,0), CV_FILLED, 1,0);
		
		cvPutText (img,"game over",cvPoint(img->width/2-100,img->height/2-40), &font, cvScalar(255,0,0, 0));
		
		char buffer_points [50];
		sprintf(buffer_points, "Points: %i", gamePoints);
		cvPutText (img,buffer_points,cvPoint(img->width/2-100,img->height/2+20), &font, cvScalar(255,0,0, 0));
		
	}
	
}
/*
  start game
 */
void startGame(){
	
	for (int i = 0; i < 10; i++) {
		allBalls[i] = new Ball(frame->width);
	}
	
	gamePoints = 0;
	gameTimeStart = time (NULL);
	gameState = 1;
}

/*
  end game
 */
void endGame(){
	gameState = 2;
}